#include <algorithm>
#include "SmithWaterman.hpp"

using namespace boost;
using namespace boost::python;
using namespace std;

SmithWaterman* SmithWaterman::instance = 0L;

SmithWaterman::SmithWaterman() {
	mat_ = PMatrix (new Matrix());
	sMatrix_ = PSimilarity_matrix(new Similarity_matrix());
	ppath_ = PPath(new Path());
	seq1_ = PSequence(new Sequencee());
	seq2_ = PSequence(new Sequencee());
}

SmithWaterman* SmithWaterman::getInstance() {
	if (!instance)
		instance = new SmithWaterman;
	return instance;
}

void SmithWaterman::startCalculation(const boost::python::object& similarity_values, string s1, string s2, int end_value) {
	int elements[16];

	seq1_->clearSequence();
	seq2_->clearSequence();

	transform(s1.begin(), s1.end(), s1.begin(), ::toupper);
	transform(s2.begin(), s2.end(), s2.begin(), ::toupper);
	seq1_->setSequence(s1);	
	seq2_->setSequence(s2);

	boost::python::list elements_py = static_cast<boost::python::list>(similarity_values.attr("elements"));
	
	for(int i = 0; i < 16; ++i)
		 elements[i] = extract<int>(elements_py[i].attr("value"));

	sMatrix_->createSimilarityMatrix(elements);
	mat_->createMatrix(seq1_, seq2_, sMatrix_);

	ppath_->findPath(mat_, end_value);
	ppath_->reconstructAlignment(seq1_, seq2_);
}

string SmithWaterman::getFirstResult() {
	return (ppath_->getFirstAlignment()->getSequence());
}

string SmithWaterman::getSecondResult() {
	return (ppath_->getSecondAlignment()->getSequence());
}
